﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Xml;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.Win32;
using TXLooker.WorkItemExtention.Properties;

namespace TXLooker.WorkItemExtention.Core
{
    public class QueryTextBuilder
    {
        private String queryText;
        private String sourceQuery;
        public BindingList<ColumnInfo> SourceColumns { get; set; }
        public BindingList<ColumnInfo> TargetColumns { get; set; }
        private String columnsWidths;

        private String columnsWidthsFromRegistry;

        public void InitBuilder(StoredQuery tfsStoredQuery)
        {
            sourceQuery = tfsStoredQuery.QueryText;
            var queryID = tfsStoredQuery.QueryGuid.ToString();
            columnsWidthsFromRegistry = GetColumnsWidthsFromRegistry(queryID);

            queryText = String.Empty;

            var helpList = new List<ColumnInfo>();

            foreach (FieldDefinition definition in tfsStoredQuery.Project.Store.FieldDefinitions)
            {
                helpList.Add(new ColumnInfo
                                 {
                                     ReferenceName = definition.ReferenceName,
                                     ColumnHeaderText = definition.Name,
                                     Width = GetColumnWidthFromRegistry(definition.Name)
                                 });
            }

            helpList.Sort();

            SourceColumns = new BindingList<ColumnInfo>(helpList);

            TargetColumns = new BindingList<ColumnInfo>();
            var find = sourceQuery.Remove(sourceQuery.IndexOf("FROM"));
            var matches = Regex.Matches(find, @"(\[.*?\])");
            foreach (var match in matches)
            {
                foreach (var column in SourceColumns)
                {
                    var Contains = match.ToString().ToLower().Contains(column.ColumnHeaderText.ToLower().Replace(" ", ""));
                    if (!Contains) continue;
                    if (TargetColumns.Contains(column)) continue;
                    TargetColumns.Add(column);
                    break;
                }
            }

            foreach (var column in TargetColumns)
            {
                SourceColumns.Remove(column);
            }
        }

        public string GetColumnWidthFromRegistry(String columnHeaderText)
        {
            var xDoc = new XmlDocument();
            if (String.IsNullOrEmpty(columnsWidthsFromRegistry)) return "n/a";
            if (!columnsWidthsFromRegistry.Contains(columnHeaderText)) return "n/a";
            xDoc.LoadXml(columnsWidthsFromRegistry);
            //var find = "Columns/Column[@Name=" + columnHeaderText + "]";
            //var find = "Column[@Name=" + columnHeaderText + "]";

            var root = xDoc.DocumentElement;

            var find = "Column[@Name=\"" + columnHeaderText + "\"]";

            var column = root.SelectSingleNode(find);
            var result = column == null ? "n/a" : column.Attributes["Width"].Value;
            return result;// column == null ? "n/a" : column.Attributes["Width"].Value;
        }

        private static String GetColumnsWidthsFromRegistry(String queryID)
        {
            var key = Resources.REGISTRY_FULL_PATH;
            return Registry.GetValue(key, queryID, String.Empty).ToString();
        }

        public void RemoveColumn(int columnInd)
        {
            if (columnInd < 0) return;
            var i = 0;
            if (SourceColumns.Count >= 1)
            {
                while (TargetColumns[columnInd].CompareTo(SourceColumns[i]) > 0)
                {
                    i++;
                    if (i == SourceColumns.Count)
                        break;
                }
            }
            SourceColumns.Insert(i, TargetColumns[columnInd]);

            TargetColumns.RemoveAt(columnInd);
        }

        public void AddColumn(int columnInd)
        {
            if (columnInd < 0) return;
            TargetColumns.Add(SourceColumns[columnInd]);
            SourceColumns.RemoveAt(columnInd);
        }

        public void MoveColumnUp(int columnInd)
        {
            if (columnInd < 1) return;

            var buf = TargetColumns[columnInd - 1];
            TargetColumns[columnInd - 1] = TargetColumns[columnInd];
            TargetColumns[columnInd] = buf;
        }

        public void MoveColumnDown(int columnInd)
        {
            if (columnInd >= TargetColumns.Count - 1) return;
            var buf = TargetColumns[columnInd + 1];
            TargetColumns[columnInd + 1] = TargetColumns[columnInd];
            TargetColumns[columnInd] = buf;

        }

        public String GetQueryText()
        {
            queryText = String.Empty;

            queryText += "SELECT ";

            foreach (var column in TargetColumns)
            {
                queryText += SurroundWithBrackets(column.ReferenceName);
            }

            queryText = queryText.Replace("][", "], [");

            queryText += sourceQuery.Remove(0, sourceQuery.IndexOf("FROM"));
            queryText = queryText.Replace("FROM", " FROM");
            return queryText;
        }

        public String GetColumnWidths()
        {
            columnsWidths = String.Empty;

            foreach (var column in TargetColumns)
            {
                if (column.Width == "n/a") continue;
                columnsWidths += String.Format("<Column Name=\"{0}\" Width=\"{1}\" />", column.ColumnHeaderText, column.Width);
            }
            columnsWidths = String.Format("<Columns>{0}</Columns>", columnsWidths);

            return columnsWidths;
        }

        #region Helpers

        private static string SurroundWithBrackets(string columnReferenceName)
        {
            return String.Format("[{0}]", columnReferenceName);
        }

        #endregion
    }
}